from datetime import datetime
from info.models import User
from info.modules.index.views import index
from . import passport_blu
import random
import re
from flask import request, abort, make_response, current_app, jsonify, json, session, redirect, url_for
from info import redis_store, constants, db
from info.libs.yuntongxun.sms import CCP
from info.utils.captcha.captcha import captcha
from info.utils.response_code import RET


@passport_blu.route('/logout')
def logout():
    """右上角登出"""
    session.pop("user_id")
    session.pop("nick_name")
    session.pop("mobile")
    session.pop('is_admin', None)
    # return redirect(url_for('index'))  # 如何利用重定向
    return jsonify(errno=RET.OK, errmsg="退出成功")


@passport_blu.route('/login',methods=["POST"])
def login():
    """登录
    # 1.获取参数：手机号，密码
    # 2.校验参数
    # 3.从数据库取出手机号和密码进行比对
    # 4.记录登录状态
    # 5.返回成功响应
    """

    # 1.获取参数：手机号和密码
    params_dict = request.json
    mobile = params_dict.get("mobile")
    password = params_dict.get("password")
    # 2.判断数据是否齐全
    if not all([mobile,password]):
        return jsonify(errno=RET.DATAERR, errmsg="参数错误")

    # 3.判断手机号格式是否正确
    if not re.match(r"1[3579]\d{9}$", mobile):
        return jsonify(errno=RET.DATAERR, errmsg="手机号格式不正确")

    # 4.校验密码是否存在
    # 先查询指定手机号账户是否存在
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询错误")

    # 判断用户是否存在
    if not user:
        return jsonify(errno=RET.NODATA, errmsg="该用户不存在")

    # 校验登录的密码和当前的用户的密码是否一致
    # check_password 一个函数，可以校验密码是否正确
    if not user.check_password(password):
        return jsonify(errno=RET.PWDERR, errmsg="密码错误")

    # 5.记录登录状态
    session["user_id"] = user.id
    session["nick_name"] = user.mobile
    session["mobile"] = user.mobile

    # 设置当前用户最后一次登录时间
    user.last_login = datetime.now()

    # 如果在视图函数中，对模型身上的属性有修改，那么需要commit到数据库
    # 但其实可以不用自己去写，db.session.commit(),前提是将SQLACHEMY_COMMIT_ON_TEARDOWN设为True
    # try:
    #     db.session.commit()
    # except Exception as e:
    #     db.session.rollback()
    #     current_app.logger.error(e)

    # 6.返回登录结果
    return jsonify(errno=RET.OK, errmsg="登录成功")


@passport_blu.route('/register', methods=["POST"])
def register():
    """注册后端实现"""
    # 1.获取参数电话号码，短信验证码，密码
    # 2.校验参数
    # 3.从redis中取出真实的短信验证码
    # 4.和用户输入的验证码进行对比
    # 5.将用户的数据写入redis数据库
    # 6.保存当前用户的状态

    # 1.获取参数：电话号码，短信验证码，密码
    params_dict = request.json
    mobile = params_dict.get("mobile")
    sms_code = params_dict.get("smscode")
    password = params_dict.get("password")
    # 2.判断参数是否存在
    if not all([mobile,sms_code,password]):
        return jsonify(errno=RET.DATAERR, errmsg="参数错误")
    # 3.判断按手机号格式是否正确
    if not re.match(r"^1[3579][0-9]{9}$",mobile):
        return jsonify(errno=RET.DATAERR, errmsg="手机号输入错误")
    # 4.从redis 中取出短信验证码
    try:
        real_sms_code = redis_store.get("msg_" + mobile)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询错误")
    # 5.判断取出的验证码是否为空
    if not real_sms_code:
        return jsonify(errno=RET.NODATA, errmsg="短信验证码已过期")
    # 6.如果用户输入短信验证码和真实验证码不相等，则注册失败
    if real_sms_code != sms_code:
        return jsonify(errno=RET.DATAERR, errmsg="验证码错误，注册失败")
    # 7.初始化User模型，将数据添加到数据库
    user = User()
    user.mobile = mobile
    user.nick_name = mobile
    user.password = password
    user.last_login = datetime.now()

    # 对密码进行处理
    # password是一个函数，可以对用户的密码进行哈希加密处理
    user.password = password
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.debug(e)
        db.roll_back()
        return jsonify(errno=RET.DBERR, errmsg="注册失败")
    # 8.保存用户登录状态
    session["user_id"] = user.id
    session["nick_name"] = user.mobile
    session["mobile"] = user.mobile
    # 9.返回注册结果
    return jsonify(errno=RET.OK,errmsg="注册成功")


@passport_blu.route('/sms_code', methods=["POST"])
def smsCode():
    """获取短信验证码"""
    # 1.获取参数
    # 2.取出手机号，用户输入验证码，图片编码
    # 3.校验参数
    # 4.取出redis中验证码文字与用户输入验证码进行比较
    # 5.生成短信验证码数字和手机号一起发送给容联云
    # 6.保存短信验证码以便注册时校对

    # 1.获取参数 '{"mobile":"mobile","image_code":"imageCode","image_code_id":"imageCodeId"}'
    # params_dict  = json.loads(request.data)
    params_dict = request.json  # 将json字符串转为字典
    print(params_dict)
    current_app.logger.debug(params_dict)
    mobile = params_dict.get("mobile")
    imageCode = params_dict.get("image_code")
    imageCodeId = params_dict.get("image_code_id")
    # 2.校验参数是否齐全
    if not all([mobile, imageCode, imageCodeId]):
        return jsonify(errno=RET.DATAERR, errmsg="参数错误")
    # 3.校验手机号格式是否正确
    if not re.match(r'1[2357]\d{9}$',mobile):
        return jsonify(errno=RET.DATAERR, errmsg="手机格式不正确")
    # 4.取出redis中之前保存的验证码文字
    try:
        real_image_code = redis_store.get('imageCode_' + imageCodeId)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(errno=RET.DBERR, errmsg="数据库查询错误")
    # 5.判断取出的值是过期
    if not real_image_code:
        return jsonify(errno=RET.DBERR, errmsg="验证码已过期")
    # 6.和用户输入的验证码进行比较
    if real_image_code.upper() != imageCode.upper():
        return jsonify(errno=RET.NODATA, errmsg="验证码输入不正确")
    # 7.发送短信验证码
    msg_code = "%06d" % random.randint(0,999999)
    current_app.logger.debug(msg_code)
    # result = CCP().send_template_sms(mobile, [msg_code, constants.IMAGE_CODE_REDIS_EXPIRES/60], "1")
    # if result != 0:
    #     return jsonify(errno=RET.DATAERR, errmsg="短信发送失败")
    # 8.保存短信验证码
    try:
        redis_store.set("msg_" + mobile, msg_code)
    except Exception as e:
        current_app.logger.debug(e)
        return jsonify(errno=RET.DBERR, errmsg="数据保存失败")
    # 9.返回成功响应
    return jsonify(errno=RET.OK, errmsg="发送成功")


@passport_blu.route('/image_code')
def imageCode():
    """获取验证码"""
    # 1.获取参数
    # 2.判断参数是否存在
    # 3.随机生成验证码图片和文字
    # 4.将验证码文字保存在redis中
    # 5.给浏览器返回验证码图片

    # 1.获取图片编码
    imageCodeId = request.args.get('imageCodeId')
    # 2.判断参数是否存在
    if not imageCodeId:
        return abort(404)
    # 3.随机生成验证码
    name, text, image = captcha.generate_captcha()
    # 4.将验证码文字保存在redis中
    try:
        redis_store.set('imageCode_' + imageCodeId, text,constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.debug(e)
        abort(500)
    # 5.给浏览器返回验证码图片
    response = make_response(image)
    response.headers["Content-Type"] = "image/jpg"
    return response